/**
  * Author: Mei
  * Date: 2020-12-12 19:25
  * Description: 右值   被move之后 原先那个就不能再用了
  * 当我们只要一些对象中的数据 没必要使用这些对象 我们就可以生成临时对象  但为了生成临时对象 例如对象中有指针类型的话
  *     我们只需要复制这个指针地址 然后切断原先的地址  避免了批量的调用赋值构造函数
  *     但大部分是需要我们自己写右值表达式的定义   除非库函数中有定义
  *
  *
  */
#include "../head.h"

using namespace std;

class MyString {
public:
    static size_t DCtor;
    static size_t Ctor;
    static size_t CCtor;
    static size_t CAsgn;
    static size_t MCtor;
    static size_t MAsgn;
    static size_t Dtor;
private:
    char *_data;
    size_t _len;

    void init_data(const char *s) {
        _data = new char[_len + 1];
        memcpy(_data, s, _len);
        _data[_len] = '\0';
    }

public:
    //默认构造函数
    MyString() : _data(NULL), _len(0) {
        ++DCtor;
    }

    //构造函数
    MyString(const char *p) : _len(strlen(p)) {
        ++Ctor;
        init_data(p);
    }

    //复制构造函数
    MyString(const MyString &str) : _len(str._len) {
        ++CCtor;
        init_data(str._data);
    }

    MyString(MyString &&str) noexcept : _data(str._data), _len(str._len) {
        ++MCtor;
        str._len = 0;
        str._data = NULL; //切断原来的连接
    }

    //赋值函数
    MyString &operator=(const MyString &str) {
        ++CAsgn;
        if (this != &str) {
            if (_data) delete (_data);
            _len = str._len;
            init_data(str._data);
        }
        return *this;
    }

    MyString &operator=(MyString &&str) noexcept {
        ++MAsgn;
        if (this != &str) {
            if (_data) delete (_data);
            _len = str._len;
            _data = str._data;
            str._len = 0;
            str._data = NULL; //切断原来的联系
        }
        return *this;
    }

    ~MyString() {
        ++DCtor;
        if (_data) {
            delete (_data);
        }
    }

    bool operator<<(const MyString &rhs) const {
        return string(this->_data) < string(rhs._data);
    }

    bool operator==(const MyString &rhs) const {
        return string(this->_data) == string(rhs._data);
    }

    char *get() const {
        return _data;
    }
};

size_t MyString::DCtor = 0;
size_t MyString::Ctor = 0;
size_t MyString::CCtor = 0;
size_t MyString::CAsgn = 0;
size_t MyString::MCtor = 0;
size_t MyString::MAsgn = 0;
size_t MyString::Dtor = 0;

template<typename T>
void output_static_data(const T &myStr) {
    cout << typeid(myStr).name() << "--" << endl;
    cout << "CCtor=" << T::CCtor
         << "MCtor=" << T::MCtor
         << "CAsgn=" << T::CAsgn
         << "MAsgn=" << T::MAsgn
         << "Dtor=" << T::Dtor
         << "Ctor=" << T::Ctor
         << "DCtor=" << T::DCtor
         << endl;

}

template<typename M>
void test_moveable(M c, int &value) {
    char buf[10];
    typedef typename iterator_traits<typename M::iterator>::value_type Vtype;
    clock_t timeStart = clock();

    for (int i = 0; i < value; ++i) {
        snprintf(buf, 10, "%d", rand());
        auto ite = c.end();
        c.insert(ite, Vtype(buf));
    }
    cout << "construction,milli -seconds:" << (clock() - timeStart) << endl;
    cout << "size()=" << c.size() << endl;
    output_static_data(*(c.begin()));

    M c1(c);
    M c2(std::move(c1));
    c1.swap(c2);
}

int main() {
    int len = 2000000;
    test_moveable(vector<MyString>(), len);

    return 0;
}